package com.example.utils;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;

import java.util.Date;
import java.util.Set;

public class DelayQueue {
    private RedisTemplate<String,String> redisTemplate=new RedisTemplate<>();
    private String queueKey;


    public  DelayQueue(RedisTemplate<String,String> redisTemplate,String queueKey){
        this.redisTemplate = redisTemplate;
        this.queueKey=queueKey;
    }

    /**
     * 把任务加入队列
     * @param value 任务
     * @param delay 延迟多少时间 ms
     */
    public void put(String value,long delay){
        //延时多久，获取到当前的时间+你想延时多久
        //时间戳-当前的时间距离时间原点（1970年1月1日0时0分0秒0毫秒）的毫秒数
        //用户全在国内，东八区 -> 2023-4-9 15:29:20 ,时间戳也可以
        //用户在国内有，小日本（东九区）也有 2023-4-9 16：29：20  考虑：东八区，鬼子的时间戳是不是一致？
        long timestamp= System.currentTimeMillis()+delay;
        redisTemplate.opsForZSet().add(queueKey,value,timestamp);
    }

    /**
     * 取消任务
     * @param value 任务
     */
    public void cancel(String value){
        redisTemplate.opsForZSet().remove(queueKey,value);
    }


    public void start(){
        new Thread(()->{
            //处理队列
            while (true) {
                //拿到任务
                Set<ZSetOperations.TypedTuple<String>> typedTuples = redisTemplate.opsForZSet().rangeByScoreWithScores(
                        queueKey,
                        0,
                        System.currentTimeMillis(),
                        0,
                        1
                );
                //执行任务-先确保拿到了任务
                if(!typedTuples.isEmpty()){
                    ZSetOperations.TypedTuple<String> next = typedTuples.iterator().next();
                    //被处理的任务要从队列中移除
                    redisTemplate.opsForZSet().remove(queueKey,next.getValue());
                    System.out.println("正在执行任务："+next.getValue()+"at:"+new Date());
                }
                //为了让大家看的比较清楚，这里我休眠1秒
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();
    }


}
